package com.itheima.health.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.itheima.health.mapper.OrderMapper;
import com.itheima.health.pojo.Member;
import com.itheima.health.pojo.Order;
import com.itheima.health.service.MemberService;
import com.itheima.health.service.OrderService;
import com.itheima.health.service.OrderSettingService;
import com.itheima.health.utils.date.DateUtils;
import com.itheima.health.utils.redis.RedisUtil;
import com.itheima.health.utils.resources.RedisConstant;
import com.itheima.health.utils.resources.RedisMessageConstant;
import com.itheima.health.utils.sms.ValidateCodeUtils;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.SneakyThrows;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@SuppressWarnings("ALL")
/**
 *    预约   ：
 *      1.  验证码判断
 *      2.  是否预约满
 *      3.  重复预约
 *      4. 预约 成功更新多表
 */
@Service
@Transactional
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Autowired
    RabbitTemplate rabbitTemplate;

    //  服务和服务之间调用     此时  订单服务 既是 服务消费者 （相对于 会员服务 、预约服务）又是 服务的提供者 （相对于 H5 移动端的请求）
    @Reference
    private OrderSettingService orderSettingService;  //  oderSettingMapper

    @Reference
    private MemberService memberService;

    @Override
    public void getCode(String email1) {
        String code = ValidateCodeUtils.generateValidateCode(4);
        //将验证码存入rabbitmq中
        rabbitTemplate.convertAndSend("boot-exchange","",email1+","+code);
        //向radis存入（验证码过期时间60s）
        RedisUtil.set(RedisMessageConstant.SENDTYPE_ORDER+email1,code,60, TimeUnit.SECONDS);
    }

    @SneakyThrows
    @Override
    @LcnTransaction  //  所有参与者  方法上即可
    public Order add(Map map) {
        //1、验证码的校验
        String validateCode = (String) map.get("validateCode");
        String email = (String) map.get("email");
        String code = RedisUtil.get(RedisMessageConstant.SENDTYPE_ORDER + email);
        if (StringUtils.isBlank(validateCode)){
            throw new RuntimeException("验证码不能为空");
        }
        if (StringUtils.isBlank(code)){
            throw new RuntimeException("验证码过期");
        }
        if (!code.equals(validateCode)){
            throw new RuntimeException("验证码错误");
        }
        //判断当天预约人数是否已满
        String orderDate = (String) map.get("orderDate");
        int count = orderSettingService.isOrderOk(orderDate);
        if (count<=0){//人数已满
            throw new RuntimeException("当天预约人数已满，请选择其他日期");
        }
        //判断当前用户是否重复预约
        Member member = memberService.findMemberByEmail(email);
        String sid = (String) map.get("setmealId");
        int mid;
        if (member!=null){//老用户,判断是否重复预约
            mid=member.getId();
            int orderExist = baseMapper.findOrderBySetMealIdAndOrderDateAndMemberId(Integer.parseInt(sid),orderDate,mid);
            if (orderExist>0){
                throw new RuntimeException("已经预约过，请择日再约");
            }
        }else {//新用户,直接注册
            member = new Member();
            member.setName((String)map.get("name"));
            member.setSex((String)map.get("sex"));
            member.setIdCard((String)map.get("idCard"));
            member.setEmail(email);
            member.setRegTime(new Date(System.currentTimeMillis()));
            mid = memberService.saveMember(member);
        }
        //更新预约人数
        orderSettingService.updateReservationByOrderDate(orderDate);

        //订单录入
        Order order = new Order();
        order.setMemberId(mid);
        order.setSetmealId(Integer.parseInt(sid));
        order.setOrderDate(DateUtils.parseString2Date(orderDate,"yyyy-MM-dd"));
        order.setOrderType((String)map.get("orderType"));
        order.setOrderStatus("未到诊");
        save(order);
        if (order.getId()!=null){
            //订单成功录入后，发送预约成功的信息给用户
            rabbitTemplate.convertAndSend("boot-exchange","",email+",恭喜你，预约成功!请在"+order.getOrderDate()+"参加体检");
        }
        return order;
    }

    @Override
    public Map findOrderInfoByOrderId(Integer id) {
        return baseMapper.findOrderInfoByOrderId(id);
    }

    @SneakyThrows
    @Override
    public Map getOrderData() {
        Date date = new Date();
        //今日预约数
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("orderdate",DateUtils.parseDate2String(date));
        int todayOrderNumber = count(orderQueryWrapper);
        //今日到诊数
        QueryWrapper<Order> orderQueryWrapper1 = new QueryWrapper<>();
        orderQueryWrapper1.eq("orderdate",DateUtils.parseDate2String(date));
        orderQueryWrapper1.eq("orderstatus","已到诊");
        int todayVisitsNumber = count(orderQueryWrapper1);
        //本周预约数
        QueryWrapper<Order> orderQueryWrapper2 = new QueryWrapper<>();
        orderQueryWrapper2.between("orderdate",DateUtils.parseDate2String(DateUtils.getFirstDayOfWeek(date)),DateUtils.parseDate2String(DateUtils.getLastDayOfWeek(date)));
        int thisWeekOrderNumber = count(orderQueryWrapper2);
        //本周到诊数
        QueryWrapper<Order> orderQueryWrapper3 = new QueryWrapper<>();
        orderQueryWrapper3.eq("orderstatus","已到诊");
        orderQueryWrapper3.between("orderdate",DateUtils.parseDate2String(DateUtils.getFirstDayOfWeek(date)),DateUtils.parseDate2String(DateUtils.getLastDayOfWeek(date)));
        int thisWeekVisitsNumber = count(orderQueryWrapper3);
        //本月预约数
        QueryWrapper<Order> orderQueryWrapper4 = new QueryWrapper<>();
        orderQueryWrapper4.between("orderdate",DateUtils.parseDate2String(DateUtils.getFirstDayDateOfMonth(date)),DateUtils.parseDate2String(DateUtils.getLastDayOfMonth(date)));
        int thisMonthOrderNumber = count(orderQueryWrapper4);
        //本月到诊数
        QueryWrapper<Order> orderQueryWrapper5 = new QueryWrapper<>();
        orderQueryWrapper5.eq("orderstatus","已到诊");
        orderQueryWrapper5.between("orderdate",DateUtils.parseDate2String(DateUtils.getFirstDayDateOfMonth(date)),DateUtils.parseDate2String(DateUtils.getLastDayOfMonth(date)));
        int thisMonthVisitsNumber = count(orderQueryWrapper5);
        Map map = new HashMap();
        map.put("todayOrderNumber",todayOrderNumber);
        map.put("todayVisitsNumber",todayVisitsNumber);
        map.put("thisWeekOrderNumber",thisWeekOrderNumber);
        map.put("thisWeekVisitsNumber",thisWeekVisitsNumber);
        map.put("thisMonthOrderNumber",thisMonthOrderNumber);
        map.put("thisMonthVisitsNumber",thisMonthVisitsNumber);
        return map;
    }

    @Override
    public List<Map> getHotSetmeal() {
        return baseMapper.getHotSetmeal();
    }
}
